package priv.abadstring.study.haoke.im.dao;

import com.mongodb.client.result.DeleteResult;
import com.mongodb.client.result.UpdateResult;
import org.bson.types.ObjectId;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.CriteriaDefinition;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Repository;
import priv.abadstring.study.haoke.im.bean.Message;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;

/**
 * MessageDAOImplByMongoDB
 *
 * @author aBadString
 * @date 2021-07-30 16:48:54
 */
@Repository
public class MessageDAOImplByMongoDB implements MessageDAO {
    @Resource
    private MongoTemplate mongoTemplate;

    @Override
    public List<Message> findListByFromAndTo(Long fromId, Long toId, Integer page, Integer rows) {

        // 对应 Long 类型的查询: db.message.find({"from._id" : new NumberLong("1002")})

        // and 是对多个条件的逻辑且: where <a> and <b>
        // andOperator 对同一个字段的多个约束, 会生成 $and 操作符

        // A 发给 B 的消息
        Criteria criteriaFrom = Criteria.where("from.id").is(fromId).and("to.id").is(toId);
        // B 发给 A 的消息
        Criteria criteriaTo = Criteria.where("from.id").is(toId).and("to.id").is(fromId);

        CriteriaDefinition criteria = new Criteria().orOperator(criteriaFrom, criteriaTo);;

        Pageable pageable = PageRequest.of(page-1, rows,
                Sort.by(Sort.Direction.ASC, "sendDate"));

        Query query = Query.query(criteria).with(pageable);
        System.out.println(query);

        return mongoTemplate.find(query, Message.class);
    }

    @Override
    public Message findMessageById(String id) {
        return this.mongoTemplate.findById(new ObjectId(id), Message.class);
    }

    @Override
    public UpdateResult updateMessageState(ObjectId id, Integer status) {
        Query query = Query.query(Criteria.where("id").is(id));
        Update update = Update.update("status", status);
        if (status == 1) {
            update.set("send_date", new Date());
        } else if (status == 2) {
            update.set("read_date", new Date());
        }
        return this.mongoTemplate.updateFirst(query, update, Message.class);
    }

    @Override
    public Message saveMessage(Message message) {
        message.setId(ObjectId.get());
        message.setSendDate(new Date());
        message.setStatus(1);
        return mongoTemplate.save(message);
    }

    @Override
    public DeleteResult deleteMessage(String id) {
        Query query = Query.query(Criteria.where("id").is(id));
        return this.mongoTemplate.remove(query, Message.class);
    }
}
